﻿using Unity;
using System;
using Prism.Ioc;
using AutoMapper;
using System.Linq;
using Prism.Unity;
using FrameWork.Core.China;
using FrameWork.Core.Device;
using FrameWork.Core.Caching;
using FrameWork.Core.Adapter;
using FrameWork.Core.Interface;
using FrameWork.Core.Aggregator;
using System.Collections.Generic;
using FrameWork.Core.Configuration;
using FrameWork.Core.Adapter.Protocol;
using FrameWork.Core.Infrastructure.Mapper;
using FrameWork.Core.Infrastructure.DependencyManagement;


namespace FrameWork.Core.Infrastructure
{
    public class InvengoEngine : IEngine
    {
        #region ___属性___
        public IContainerExtension _containerManager;

        public IContainerExtension ContainerManager
        {
            get { return _containerManager; }
        }
        #endregion

        #region ___方法___
        /// <summary>
        /// 引擎初始化
        /// </summary>
        /// <param name="config"></param>
        /// <param name="container"></param>
        public void Initialize(InvengoConfig config, IContainerExtension container)
        {
            ////////////容器对象/////////////
            this._containerManager = container;
            ////////////注入流程引擎聚合器/////////
            container.Register(typeof(IChainAggregator<,,>), typeof(ChainAggregator<,,>));
            ////////////注入缓存类/////////
            container.Register(typeof(ICacheManager), typeof(MemoryCacheManager));
            ////////////查找注入类///////////
            container.RegisterSingleton(typeof(ITypeFinder), typeof(InvengoTypeFinder));
            var typeFinder = _containerManager.Resolve<ITypeFinder>();
            ///////////搜索依赖项////////////
            RegisterDependencies(config, container);
            ///////////搜索类映射////////////
            AddAutoMapper(typeFinder);
            ///////////搜索启动任务////////////
            if (!config.IgnoreStartupTasks)
            {
                RunStartupTasks(typeFinder);
            }
        }
        /// <summary>
        /// 搜索依赖项
        /// </summary>
        /// <param name="config"></param>
        /// <param name="container"></param>
        protected virtual void RegisterDependencies(InvengoConfig config, IContainerExtension container)
        {
            var typeFinder = container.Resolve<ITypeFinder>();
            ///////////////查找子模块实现IDependencyRegistrar的子类//////////
            var drTypes = typeFinder.FindClassesOfType<IDependencyRegistrar>();
            var drInstances = new List<IDependencyRegistrar>();
            foreach (var drType in drTypes)
                drInstances.Add((IDependencyRegistrar)Activator.CreateInstance(drType));
            drInstances = drInstances.AsQueryable().OrderBy(t => t.Order).ToList();
            foreach (var dependencyRegistrar in drInstances)
                dependencyRegistrar.Register(container, typeFinder);
            ////////////////自动注入检查点///////////////
            var checkPointTypes = typeFinder.FindClassesOfType<IProcessNode>().ToList();
            checkPointTypes.ForEach(t => container.Register(typeof(IProcessNode), t, t.Name));
            ////////////////自动注入跳转代理//////////////////
            var regionTypes = typeFinder.FindClassesOfType<IRegionProxy>().ToList();
            regionTypes.ForEach(t => container.RegisterSingleton(typeof(IRegionProxy), t, t.Name));
            ////////////////自动注入设备代理//////////////////
            var deviceAdapter = typeFinder.FindClassesOfType<IDeviceAdapter>().ToList();
            deviceAdapter.ForEach(t => container.RegisterSingleton(typeof(IDeviceAdapter), t, t.Name));
            ////////////////自动注入协议对象//////////////////
            var protocols = typeFinder.FindClassesOfType<IProtocol>().ToList();
            protocols.ForEach(t => container.RegisterSingleton(typeof(IProtocol), t, t.Name));
        }
        /// <summary>
        /// 添加类映射
        /// </summary>
        /// <param name="typeFinder"></param>
        protected virtual void AddAutoMapper(ITypeFinder typeFinder)
        {
            var mapperConfigurations = typeFinder.FindClassesOfType<IOrderedMapperProfile>();
            var instances = mapperConfigurations
                .Select(mapperConfiguration => (IOrderedMapperProfile)Activator.CreateInstance(mapperConfiguration))
                .OrderBy(mapperConfiguration => mapperConfiguration.Order);
            var config = new MapperConfiguration(cfg =>
            {
                foreach (var instance in instances)
                {
                    cfg.AddProfile(instance.GetType());
                }
            });
            AutoMapperConfiguration.Init(config);
        }
        /// <summary>
        /// 启动任务
        /// </summary>
        /// <param name="typeFinder"></param>
        protected virtual void RunStartupTasks(ITypeFinder typeFinder)
        {
            var startUpTaskTypes = typeFinder.FindClassesOfType<IStartupTask>();
            var startUpTasks = new List<IStartupTask>();
            foreach (var startUpTaskType in startUpTaskTypes)
                startUpTasks.Add((IStartupTask)Activator.CreateInstance(startUpTaskType));

            startUpTasks = startUpTasks.AsQueryable().OrderBy(st => st.Order).ToList();
            foreach (var startUpTask in startUpTasks)
                startUpTask.Execute(_containerManager, typeFinder);
        }
        #endregion

        #region ___注入/获取对象___
        /// <summary>
        /// 根据类型获取对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T Resolve<T>() where T : class
        {
            return ContainerManager.Resolve<T>();
        }
        /// <summary>
        /// 根据名称获取对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <returns></returns>
        public T Resolve<T>(string name) where T : class
        {
            return ContainerManager.Resolve<T>(name);
        }
        /// <summary>
        /// 根据类型获取基对象
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public object Resolve(Type type)
        {
            return ContainerManager.Resolve(type);
        }
        /// <summary>
        /// 是否注入类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="typeName"></param>
        /// <returns></returns>
        public bool IsRegistered<T>(string typeName)
        {
            return (ContainerManager as IContainerRegistry).IsRegistered<T>(typeName);
        }
        /// <summary>
        /// 获取所有注入类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public IEnumerable<T> ResolveAll<T>()
        {
            var unityExtension = ContainerManager as UnityContainerExtension;
            return UnityContainerExtensions.ResolveAll<T>(unityExtension.Instance).ToList();
        }
        /// <summary>
        /// 获取没有注入的类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public virtual object ResolveUnregistered(Type type)
        {
            Exception innerException = null;
            foreach (var constructor in type.GetConstructors())
            {
                try
                {
                    var parameters = constructor.GetParameters().Select(parameter =>
                    {
                        var service = Resolve(parameter.ParameterType);
                        if (service == null)
                            throw new CustomException("未知依赖");
                        return service;
                    });
                    return Activator.CreateInstance(type, parameters.ToArray());
                }
                catch (Exception ex)
                {
                    innerException = ex;
                }
            }
            throw new CustomException("没找到构造函数", innerException);
        }
        #endregion
    }
}